package com.ghostbusters.fingertrack.wii;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

import javax.swing.JFrame;
import javax.swing.JPanel;

import wiiremotej.ButtonMap;
import wiiremotej.IRSensitivitySettings;
import wiiremotej.WiiRemote;
import wiiremotej.WiiRemoteExtension;
import wiiremotej.WiiRemoteJ;
import wiiremotej.event.WRAccelerationEvent;
import wiiremotej.event.WRButtonEvent;
import wiiremotej.event.WRCombinedEvent;
import wiiremotej.event.WRExtensionEvent;
import wiiremotej.event.WRIREvent;
import wiiremotej.event.WRNunchukExtensionEvent;
import wiiremotej.event.WRStatusEvent;
import wiiremotej.event.WiiRemoteListener;

import com.ghostbusters.fingertrack.control.ApplicationControl;
import com.ghostbusters.fingertrack.gui.MainFrame;
import com.intel.bluetooth.BlueCoveConfigProperties;

public class WiiMain implements WiiRemoteListener {
	public WiiRemote remote;
	private static boolean started = false;
	public static List<IRPoint> coords;
	public static JPanel graph;
	public static JFrame frame;
	public static final int DIMENSIONS = 800;
	private static final long BROADCAST_TIME = 50;

	private static long lastBroadcastTime = 0;

	private static Set<WiiSubscriber> subscribers = Collections
			.newSetFromMap(new ConcurrentHashMap<WiiSubscriber, Boolean>());

	public WiiMain(WiiRemote remote) {
		this.remote = remote;
	}

	/**
	 * @param args
	 */
	public static void main(String[] args) throws Exception {
		WiiRemoteJ.setConsoleLoggingAll();
		System.setProperty(
				BlueCoveConfigProperties.PROPERTY_JSR_82_PSM_MINIMUM_OFF,
				"true");
		try {
			WiiRemote remote = WiiRemoteJ.findRemote();
			remote.addWiiRemoteListener(new WiiMain(remote));
			remote.setAccelerometerEnabled(true);
			remote.setSpeakerEnabled(true);
			remote.setIRSensorEnabled(true, WRIREvent.BASIC,
					IRSensitivitySettings.WII_LEVEL_5);
			remote.setLEDIlluminated(0, true);
			remote.getButtonMaps().add(
					new ButtonMap(WRButtonEvent.HOME, ButtonMap.NUNCHUK,
							WRNunchukExtensionEvent.C,
							new int[] { java.awt.event.KeyEvent.VK_CONTROL },
							java.awt.event.InputEvent.BUTTON1_MASK, 0, -1));
		} catch (Throwable e) {
			e.printStackTrace();
		}

		MainFrame.setNativeLAF("Nimbus");
		MainFrame f = MainFrame.getMainFrame("Test Box");
		// frame = new JFrame();
		// frame.setTitle("IR graph");
		// frame.setSize(DIMENSIONS, DIMENSIONS);
		// frame.setResizable(false);
		// graph = new JPanel() {
		// private static final long serialVersionUID = 1962805495414620910L;
		//
		// public void paintComponent(Graphics g) {
		// if (started) {
		// g.clearRect(0, 0, DIMENSIONS, DIMENSIONS);
		//
		// for (int i = 0; i < coords.size(); i++) {
		// g.setColor(java.awt.Color.RED);
		// try {
		// g.fillOval(
		// (int) (coords.get(i).getX() * DIMENSIONS),
		// (int) (coords.get(i).getY() * DIMENSIONS),
		// 6, 6);
		// } catch (Throwable e) {
		// System.out.println("Failure!");
		// }
		// }
		//
		// }
		// }
		// };
		// graph.setSize(800, 800);
		// frame.add(graph);
		// frame.setVisible(true);

		// mouse testing
		// Mouse mouse = new Mouse();
	}

	@Override
	public void IRInputReceived(WRIREvent e) {

		coords = new ArrayList<IRPoint>();
		double x = 0, y = 0, lastx = 0, lasty = 0;
		for (int i = 0; i < e.getIRLights().length; i++) {
			if (e.getIRLights()[i] != null) {
				if (started) {
					lastx = x;
					lasty = y;
				}
				// System.out.println("IR: (" + e.getIRLights()[i].getX() + ", "
				// + e.getIRLights()[i].getX() + ")");
				x = 1f - e.getIRLights()[i].getX();
				y = 1f - e.getIRLights()[i].getY();

				// if (threshold(x, lastx) && threshold(y, lasty))
				coords.add(new IRPoint(x, y));

				if (!started)
					started = true;

			}

		}

		if (coords.size() == 1) {
			broadcastIRPoints(coords);
		} else if (coords.size() == 2) {
			// sort in descending order of y coordinate
			if (coords.get(0).getY() > coords.get(1).getY()) {
				broadcastIRPoints(coords);
			} else {
				List<IRPoint> tempCoords = new ArrayList<IRPoint>();
				tempCoords.add(coords.get(1));
				tempCoords.add(coords.get(0));
				broadcastIRPoints(coords);
			}
		} else if (coords.size() > 2) {
			System.out.println("WARNING: There is noise lights");
		}

		try {
			if (coords.size() > 0) {
				// HttpClient client = new DefaultHttpClient();
				// HttpGet get = new HttpGet(
				// "http://ec2-50-19-185-2.compute-1.amazonaws.com:8080/danceathonv1.0/api?method=user.updatePosition&userId=1&x1="
				// + coords.get(0).getX()
				// + "&y1="
				// + coords.get(0).getY()
				// + "&x2="
				// + 0
				// + "&y2="
				// + 0);
				// HttpResponse response = client.execute(get);
				// System.out.println("Request:" + response.getStatusLine());
			}
		} catch (Throwable e1) {
			e1.printStackTrace();
		}
		if (graph != null)
			graph.repaint();

	}


	@Override
	public void accelerationInputReceived(WRAccelerationEvent e) {

		// debugging code, not important
		// System.out.println("Acceleration: (" + e.getXAcceleration() + ", "
		// + e.getYAcceleration() + ", " + e.getZAcceleration() + ")");

	}

	@Override
	public void buttonInputReceived(WRButtonEvent arg0) {

	}

	@Override
	public void combinedInputReceived(WRCombinedEvent arg0) {

	}

	@Override
	public void disconnected() {

	}

	@Override
	public void extensionConnected(WiiRemoteExtension arg0) {

	}

	@Override
	public void extensionDisconnected(WiiRemoteExtension arg0) {

	}

	@Override
	public void extensionInputReceived(WRExtensionEvent arg0) {

	}

	@Override
	public void extensionPartiallyInserted() {

	}

	@Override
	public void extensionUnknown() {

	}

	@Override
	public void statusReported(WRStatusEvent arg0) {
		System.out.println(arg0.getBatteryLevel());

	}

	public static void subscribe(WiiSubscriber wiiSubscriber) {
		subscribers.add(wiiSubscriber);
	}

	public static void broadcastIRPoints(List<IRPoint> coords) {

		if (System.currentTimeMillis() - WiiMain.lastBroadcastTime > BROADCAST_TIME) {
			for (WiiSubscriber subscriber : subscribers) {
				subscriber.newPoints(coords);

			}
			lastBroadcastTime = System.currentTimeMillis();
		}
	}

	public static void unsubscribe(WiiSubscriber wiiSubscriber)
			throws Exception {
		if (!subscribers.contains(wiiSubscriber)) {
			throw new Exception(
					"Trying to unsubscribe something that doesnt exist");
		}

		subscribers.remove(wiiSubscriber);
	}

}
